package tests;

import static org.junit.Assert.*;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.LinkedList;

import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;

import sourceFiles.CentralComputer;
import sourceFiles.IRide;
import sourceFiles.RideEntry;

import Exceptions.InvalidAgeParam;
import Exceptions.InvalidCapacity;
import Exceptions.InvalidHeightParam;
import Exceptions.InvalidRideName;
import Exceptions.XMLRidesParserException;

public class CentralComputerTest {
	static private String masterXMLFilePath;
	static private String copyXMLFilePath;
	static final private String[] LEGAL_RIDE_NAME = { "ride1", "ride2", "ride3" };
	static final private int[] LEGAL_RIDE_ID = { 1, 2, 236321 };
	static final private int[] LEGAL_MAX_CAPACITY = { 1, 2, 34335 };
	static final private int[] LEGAL_MIN_AGE = { 1, 2, 100 };
	static final private int[] LEGAL_MIN_HEIGHT = { 1, 2, 100 };
	static final private boolean[] IS_EXTREME_RIDE = { true, false, true };
	static final private int[] ILLEGAL_RIDE_ID = { 0, -1, -42 };
	static final private int[] ILLEGAL_MAX_CAPACITY = { 0, -1, -42 };
	static final private int[] ILLEGAL_MIN_AGE = { 0, -1, -56 };
	static final private int[] ILLEGAL_MIN_HEIGHT = { 0, -1, -96 };

	@BeforeClass
	public static void setUpBeforeClass() throws Exception {
		String currentPath = new java.io.File(".").getCanonicalPath();
		masterXMLFilePath = currentPath + "\\src\\tests\\TestsMaster.xml";
		copyXMLFilePath = currentPath + "\\src\\tests\\Tests.xml";
	}

	@Before
	public void setUp() throws Exception {
		InputStream inStream = null;
		OutputStream outStream = null;

		File afile = new File(masterXMLFilePath);
		File bfile = new File(copyXMLFilePath);

		inStream = new FileInputStream(afile);
		outStream = new FileOutputStream(bfile);

		byte[] buffer = new byte[1024];

		int length;
		// copy the file content in bytes
		while ((length = inStream.read(buffer)) > 0) {

			outStream.write(buffer, 0, length);
		}
		inStream.close();
		outStream.close();
	}

	@Test
	public void testCentralComputerCtor() throws XMLRidesParserException {
		try {
			CentralComputer cc = new CentralComputer(null);
			fail("tried to create a CentralComputer with an invalid file");
		} catch (XMLRidesParserException e) {
		}
		try {
			CentralComputer cc = new CentralComputer("aaa");
			fail("tried to create a CentralComputer with an invalid file");
		} catch (XMLRidesParserException e) {
		}
		CentralComputer cc = new CentralComputer(copyXMLFilePath);
	}

	// @Test
	// public void testGetTicketsSold() {
	// fail("Not yet implemented");
	// }
	//
	// @Test
	// public void testSetTicketsSold() {
	// fail("Not yet implemented");
	// }
	//
	// @Test
	// public void testGetSupervisorStation() {
	// fail("Not yet implemented");
	// }
	//
	// @Test
	// public void testSetSupervisorStation() {
	// fail("Not yet implemented");
	// }
	//
	// @Test
	// public void testGetGuardiansList() {
	// fail("Not yet implemented");
	// }
	//
	// @Test
	// public void testSetGuardiansList() {
	// fail("Not yet implemented");
	// }
	//
	// @Test
	// public void testGetChildrenList() {
	// fail("Not yet implemented");
	// }
	//
	// @Test
	// public void testSetChildrenList() {
	// fail("Not yet implemented");
	// }
	//
	// @Test
	// public void testGetRidesList() {
	// fail("Not yet implemented");
	// }
	//
	// @Test
	// public void testSetRidesList() {
	// fail("Not yet implemented");
	// }
	//
	// @Test
	// public void testGetRidesCatalog() {
	// fail("Not yet implemented");
	// }
	//
	// @Test
	// public void testSetRidesCatalog() {
	// fail("Not yet implemented");
	// }
	//
	// @Test
	// public void testGetApplicationList() {
	// fail("Not yet implemented");
	// }
	//
	// @Test
	// public void testSetApplicationList() {
	// fail("Not yet implemented");
	// }

	@Test
	public void testCreateRide() throws XMLRidesParserException,
			InvalidCapacity, InvalidAgeParam, InvalidHeightParam,
			InvalidRideName {
		CentralComputer cc = new CentralComputer(copyXMLFilePath);
		testIllegalRideNameInCreateRide(cc);
		testIllegalMaxCapacityInCreateRide(cc);
		testIllegalMinAgeInCreateRide(cc);
		testIllegalMinHeightInCreateRide(cc);
		testLegalParamsInCreateRide(cc);
	}

	private void testLegalParamsInCreateRide(CentralComputer cc)
			throws InvalidRideName, InvalidCapacity, InvalidAgeParam,
			InvalidHeightParam {
		LinkedList<IRide> ridesList = cc.getRidesList();
		LinkedList<RideEntry> ridesCatalog = cc.getRidesCatalog();
		assertTrue(ridesList.size() == 0 && ridesCatalog.size() == 0);
		for (int i = 0; i < LEGAL_RIDE_NAME.length; i++) {
			cc.createRide(LEGAL_RIDE_NAME[i], true, LEGAL_MAX_CAPACITY[i],
					LEGAL_MIN_AGE[i], LEGAL_MIN_HEIGHT[i]);
		}
		ridesList = cc.getRidesList();
		ridesCatalog = cc.getRidesCatalog();
		assertTrue(ridesList.size() == LEGAL_RIDE_NAME.length
				&& ridesCatalog.size() == LEGAL_RIDE_NAME.length);
//		for (int i = 0; i < ridesList.size(); i++) {
//			//TODO check again about setters and getters
//		}
	}

	private void testIllegalMinHeightInCreateRide(CentralComputer cc)
			throws InvalidRideName, InvalidCapacity, InvalidAgeParam {
		for (int i = 0; i < ILLEGAL_MIN_HEIGHT.length; i++) {
			try {
				cc.createRide(LEGAL_RIDE_NAME[i], true, LEGAL_MAX_CAPACITY[i],
						LEGAL_MIN_AGE[i], ILLEGAL_MIN_HEIGHT[i]);
				fail("Tried to create ride with an illegal minHeight value of "
						+ ILLEGAL_MIN_HEIGHT[i]);
			} catch (InvalidHeightParam e) {
			}
		}
	}

	private void testIllegalMinAgeInCreateRide(CentralComputer cc)
			throws InvalidRideName, InvalidCapacity, InvalidHeightParam {
		for (int i = 0; i < ILLEGAL_MIN_AGE.length; i++) {
			try {
				cc.createRide(LEGAL_RIDE_NAME[i], true, LEGAL_MAX_CAPACITY[i],
						ILLEGAL_MIN_AGE[i], LEGAL_MIN_HEIGHT[i]);
				fail("Tried to create ride with an illegal minAge value of "
						+ ILLEGAL_MIN_AGE[i]);
			} catch (InvalidAgeParam e) {
			}
		}
	}

	private void testIllegalMaxCapacityInCreateRide(CentralComputer cc)
			throws InvalidRideName, InvalidAgeParam, InvalidHeightParam {
		for (int i = 0; i < ILLEGAL_MAX_CAPACITY.length; i++) {
			try {
				cc.createRide(LEGAL_RIDE_NAME[i], true,
						ILLEGAL_MAX_CAPACITY[i], LEGAL_MIN_AGE[i],
						LEGAL_MIN_HEIGHT[i]);
				fail("Tried to create ride with an illegal maxCapacity value of "
						+ ILLEGAL_MAX_CAPACITY[i]);
			} catch (InvalidCapacity e) {
			}
		}
	}

	private void testIllegalRideNameInCreateRide(CentralComputer cc)
			throws InvalidCapacity, InvalidAgeParam, InvalidHeightParam {
		try {
			cc.createRide(null, true, LEGAL_MAX_CAPACITY[0], LEGAL_MIN_AGE[0],
					LEGAL_MIN_HEIGHT[0]);
			fail("Tried to create ride with a null name parameter");
		} catch (InvalidRideName e) {
		}
	}

	@Test
	public void testUpdateRide() {
		fail("Not yet implemented");
	}

	@Test
	public void testAddGuardian() {
		fail("Not yet implemented");
	}

	@Test
	public void testAddChildToGuardian() {
		fail("Not yet implemented");
	}

	@Test
	public void testConnectGuardian() {
		fail("Not yet implemented");
	}

	@Test
	public void testBuyingProcess() {
		fail("Not yet implemented");
	}

	@Test
	public void testPerformBilling() {
		fail("Not yet implemented");
	}

	@Test
	public void testCancelAcquisition() {
		fail("Not yet implemented");
	}

	@Test
	public void testValidateChildForRide() {
		fail("Not yet implemented");
	}

	@Test
	public void testRetrieveChildrenLocation() {
		fail("Not yet implemented");
	}

	@Test
	public void testRetrieveChildETicket() {
		fail("Not yet implemented");
	}

}
